<?php

defined('BASEPATH') or die('forbidden');

/**
 * 后台权限控制类
 * @author  Karson
 * @name    auth.php
 * @since   2013-6-20 10:55:12
 */
class Auth {

    var $config, $db;
    var $user_id = 0;
    var $username = '';
    var $sessionid = '';
    var $fields = array('user_id' => 0, 'username' => '', 'nickname' => '', 'logined' => 0, 'id' => 0, 'face' => '', 'sex' => '', 'url' => '');
    var $purse = array('copper' => 0, 'gold' => 0, 'geste' => 0, 'gift' => 0, 'id' => 0, 'inter' => 0);
    var $role_id = 0;
    var $role_name = '';
    var $role_rank = 0;
    var $role_permission = array();
    var $error = '';

    function __construct() {
        $framework = &get_instance('controller');
        $this->config = &$framework->config;
        $this->db = &$framework->db;
        $this->cache = &$framework->cache;
        $this->cookie = &$framework->cookie;
        $this->session = &$framework->session;
        $this->fields['face'] = $this->config['res_url'] . '/images/common/face160.gif';
        $this->fields['username'] = translate('GUEST');
        $this->fields['nickname'] = translate('GUEST');
        $this->is_login();
    }

    /**
     * 判断用户是否登录
     * @return bool
     */
    function is_login() {
        $this->user_id = $this->user_id ? $this->user_id : $this->cookie->get('user_id');
        if ($this->user_id) {
            if ($this->fields['logined'] == 1)
                return true;
            if ($this->error)
                return false;
            $row = $this->db->one("SELECT * FROM {pre}admin WHERE id='{$this->user_id}'");
            if (!is_array($row)) {
                $this->error = translate('COMMON_AUTH_USER_NOT_FOUND');
                return false;
            }
//            if ($this->cookie->get('sessionid') != $row['sessionid']) {
//                $this->logout();
//                $this->error = '该用户已经在另外一点登录';
//                return false;
//            }
            $safecode = md5($row['id'] . md5($row['password']));
            if ($safecode != $this->cookie->get('safecode')) {
                $this->error = translate('COMMON_AUTH_USER_HAS_CHANGED');
                return false;
            }
            //获取角色信息及权限
            $role = $this->get_role($row['role_id']);
            $this->user_id = $row['id'];
            $this->username = $row['username'];
            $this->nickname = $row['username'];
            $this->role_id = $role['id'];
            $this->role_name = $role['name'];
            $this->role_rank = $role['rank'];
            $this->role_permission = $role['permission'];
            $this->sessionid = $row['sessionid'];
            $this->fields = $row;
            //附加其它信息
            $this->fields['logined'] = 1;
            $this->fields['user_id'] = $row['id'];
            $this->fields['role_name'] = $role['name'];
            $this->fields['role_rank'] = $role['rank'];
            $this->fields['role_permission'] = $role['permission'];
            $this->error = '';
            unset($row, $role);
            return true;
        } else {
            $this->error = '请登录后再进行操作';
            return false;
        }
    }

    function login($username, $password, $keeptime = 0) {
        $row = $this->db->one("SELECT * FROM {pre}admin WHERE username='{$username}'");
        if (is_array($row)) {
            //登录失败大于3次则开启验证码模式
            if ($row['loginfailure'] >= 3) {
                $captcha = strtoupper($_POST['captcha']);
                if ($captcha == '' || strlen($captcha) != 4) {
                    $this->error = translate('INDEX_VERIFICATION_CODE');
                    return false;
                }

                if (!isset($_SESSION['captcha']) || $captcha != $_SESSION['captcha']) {
                    $this->error = translate('INDEX_INVALID_VERIFICATION_CODE');
                    return false;
                }
            }
            if ($row['password'] == md5($password)) {
                $role = $this->get_role($row['role_id']);
                if ($role) {
                    if (!isset($_SESSION))
                        session_start();
                    $sessionid = session_id();
                    $row['sessionid'] = $sessionid;
                    $this->cookie->set('user_id', $row['id'], $keeptime, base_url());
                    $this->cookie->set('username', $row['username'], 86400 * 365, base_url());
                    $this->cookie->set('safecode', md5($row['id'] . md5($row['password'])), $keeptime, base_url());
                    $this->cookie->set('sessionid', $sessionid, $keeptime, base_url());
                    $this->user_id = $row['id'];
                    $this->username = $row['username'];
                    $this->nickname = $row['username'];
                    $this->role_id = $role['id'];
                    $this->role_name = $role['name'];
                    $this->role_rank = $role['rank'];
                    $this->role_permission = $role['permission'];
                    $this->sessionid = $row['sessionid'];
                    $this->fields = $row;
                    //附加其它信息
                    $this->fields['logined'] = 1;
                    $this->fields['user_id'] = $row['id'];
                    $this->fields['role_name'] = $role['name'];
                    $this->fields['role_rank'] = $role['rank'];
                    $this->fields['role_permission'] = $role['permission'];
                    $this->error = '';
                    $time = time();
                    $this->db->update("{pre}admin", array('logintime' => $time, 'sessionid' => $sessionid, 'loginfailure' => '0'), array('id' => $row['id']));
                    unset($row, $role);
                    return true;
                } else {
                    $this->error = translate('COMMON_AUTH_USER_PERMISSIONS_ERROR');
                    return false;
                }
            } else {
                $this->db->update("{pre}admin", array('loginfailure' => '#+1'), array('id' => $row['id']));
                $this->error = translate('COMMON_AUTH_USER_INVALID_PASSWORD');
                return false;
            }
        } else {
            $this->error = translate('COMMON_AUTH_USER_INVALID_USERNAME_PASSWORD');
            return false;
        }
    }

    /**
     * 注销登录退出
     * @return bool
     */
    function logout($path = "/") {
        $this->user_id = 0;
        $this->username = '';
        $this->sessionid = '';
        $this->fields = null;
        $this->cookie->clear('user_id', $path);
        $this->cookie->clear('is_admin', $path);
        $this->cookie->clear('safecode', $path);
        $this->cookie->clear('username', $path);
        $this->cookie->clear('sessionid', $path);
        $this->cookie->clear('pf', $path);
        $this->cookie->clear('openid', $path);
        $this->session->clear();
        return true;
    }

    /**
     * 读取会员的钱包数据
     * @param int $userId
     * @return array
     */
    function get_purse($userId = null) {
        $user = $this->get_user_data($userId);
        return array(
            "copper" => $user['copper'],
            "gold" => sprintf("%.2f", $user['gold']),
            "geste" => $user['geste'],
            "gift" => $user['gift'],
            "id" => $user['id'],
            "inter" => $user['inter']
        );
    }

    /**
     * 读取玩家的消息信息
     * @param int $userId
     * @return array
     */
    function get_player($userId = null) {
        $user = $this->get_user_data($userId);
        return array(
            "id" => $user['id'],
            "name" => $user['nickname'],
            "camp" => $user['campId'],
            "vip" => $user['vip']
        );
    }

    /**
     * 读取玩家的体力等信息
     * @return array
     */
    function get_stamina($user = null) {
        $user = is_null($user) ? $this->fields : $user;
        $buyPhyCount = $buyEndCount = $lastBuyEndTime = $lastBuyPhyTime = 0;
        $starttime = get_unixtime();
        $endtime = get_unixtime('day', 0, 'end');
        $this->db->query("SELECT * FROM {pre}user_day WHERE type IN ('buyphysical', 'buyendurance') AND user_id='{$user['id']}' AND createtime>='{$starttime}' AND createtime<={$endtime} ORDER BY id DESC");
        while ($row = $this->db->get_array()) {
            if ($row['type'] == 'buyphysical') {
                $buyPhyCount += $row['memo'];
                $lastBuyEndTime = $row['createtime'] * 1000;
            }
            if ($row['type'] == 'buyendurance') {
                $buyEndCount += $row['memo'];
                $lastBuyPhyTime = $row['createtime'] * 1000;
            }
        }
        return array(
            "id" => $user['id'],
            "endurance" => $user['endurance'],
            "physical" => $user['physical'],
            "refreshPhysicalTime" => $user['refreshPhysicalTime'],
            "refreshEnduranceTime" => $user['refreshEnduranceTime'],
            "lastBuyEndTime" => $lastBuyEndTime,
            "lastBuyPhyTime" => $lastBuyPhyTime,
            "buyEndCount" => vip_value('strengthBuyNum', $user['vip']) - $buyEndCount,
            "buyPhyCount" => vip_value('staminaBuyNum', $user['vip']) - $buyPhyCount,
        );
    }

    /**
     * 获取指定角色的权限数据
     * @param int $role_id 角色ID
     * @param bool $unserialize 是否需要反序列化
     * @return mixed
     */
    function get_permission($role_id = 0, $unserialize = true) {
        $role_id = intval($role_id);
        $role_data = $this->get_role_data();
        if (!is_array($role_data))
            return false;
        foreach ($role_data as $key => $value) {
            if ((string) $value['id'] === (string) $role_id) {
                $permission = $unserialize ? unserialize($value['permission']) : $value['permission'];
                return $permission;
            }
        }
        return false;
    }

    /**
     * 修改指定角色的权限
     * @param int $role_id 角色ID
     * @param mixed $permission 权限数据
     * @param bool $serialize 是否序列化数据
     * @return mixed 成功返回影响的数据
     */
    function set_permission($role_id, $permission, $serialize = true) {
        $value['permission'] = $serialize ? serialize($permission) : $permission;
        $row = $this->db->one("SELECT * FROM {pre}role WHERE id='{$role_id}'");
        if (is_array($row)) {
            $value['modifytime'] = time();
            $this->db->update("{pre}role", $value, array("id" => $role_id));
            $this->set_role_data();
            return true;
        } else {
            return false;
        }
    }

    /**
     * 创建和修改角色信息
     * @param string $name 角色名称
     * @param mixed $permission 角色权限
     * @param bool $overwrite 是否覆盖已经存在的角色
     */
    function set_role($name, $permission = array(), $overwrite = true) {
        $value = array('name' => $name, 'permission' => serialize($permission));
        $row = $this->db->one("SELECT * FROM {pre}role WHERE name='{$name}'");
        if (is_array($row)) {
            if ($overwrite) {
                $value['modifytime'] = time();
                $this->db->update("{pre}role", $value, "name='{$name}'");
            } else {
                return false;
            }
        } else {
            $value['createtime'] = time();
            $this->db->insert("{pre}role", $value);
        }
        $this->set_role_data();
        return true;
    }

    /**
     * 获取指定角色的数据
     * @param int $role_id 角色ID
     * @return mixed
     */
    function get_role($role_id) {
        $role_data = $this->get_role_data();
        if (!is_array($role_data))
            return false;
        foreach ($role_data as $key => $value) {
            if ((string) $value['id'] === (string) $role_id) {
                $value['permission'] = unserialize($value['permission']);
                return $value;
            }
        }
        return false;
    }

    /**
     * 删除角色信息
     * @param int $role_id 角色ID
     * @return bool 删除成功与否
     */
    function delete_role($role_id) {
        if ($this->db->simple("DELETE FROM {pre}role WHERE id = '{$role_id}'")) {
            $this->set_role_data();
            return true;
        } else {
            return false;
        }
    }

    /**
     * 判断是否具有访问uri的权限
     * @param string $uri 指定的uri，默认为空，为空时取当前的控制器和方法
     * @return bool
     */
    function check_uri_permission($uri = '') {
        if (!$this->is_login())
            return false;
        if ($uri == '')
            $uri = current_action();
        $permission = $this->role_permission;
        return is_array($permission) && isset($permission['uri']) && in_array($uri, $permission['uri']) ? true : false;
    }

    /**
     * 判断当前浏览者权限
     * @param string $catalog 栏目名称
     * @param string $action 操作权限
     * @param string $segment 第三段
     * @return bool
     */
    function check_level($rank = 1, $catalog = null, $action = null, $segment = null) {
        if (!$this->is_login())
            return false;
        //判断是否拥有该权限等级
        if ($this->role_rank == 100)
            return true;
        if ($this->role_rank < $rank)
            return false;
        if (is_array($this->role_permission)) {
            $nowurl = $_SERVER['REQUEST_URI'];
            //判断拒绝URI
            if (isset($this->role_permission['deny_uri']) && count($this->role_permission['deny_uri']) > 0) {
                foreach ($this->role_permission['deny_uri'] as $key => $value) {
                    $value = trim($value);
                    if ($value == '')
                        continue;
                    $urllen = strlen($value);
                    if (substr($nowurl, 0, $urllen) == $value)
                        return false;
                }
            }
            //判断允许URI
            if (isset($this->role_permission['allow_uri']) && count($this->role_permission['allow_uri']) > 0) {
                foreach ($this->role_permission['allow_uri'] as $key => $value) {
                    $value = trim($value);
                    if ($value == '')
                        continue;
                    $urllen = strlen($value);
                    if (substr($nowurl, 0, $urllen) == $value)
                        return true;
                }
            }
            //判断指定栏目的权限
            if (!is_null($catalog) && !is_null($action) && !is_null($segment)) {
                if (isset($this->role_permission['admin'][$catalog]) && is_array($this->role_permission['admin'][$catalog]) && in_array($action, $this->role_permission['admin'][$catalog]) && isset($this->role_permission['admin'][$catalog][$action]) && is_array($this->role_permission['admin'][$catalog][$action]) && in_array($segment, $this->role_permission['admin'][$catalog][$action])
                )
                    return true;
            } else if (!is_null($catalog) && !is_null($action)) {
                if (isset($this->role_permission['admin'][$catalog]) && is_array($this->role_permission['admin'][$catalog]) && in_array($action, $this->role_permission['admin'][$catalog])
                )
                    return true;
            } else if (!is_null($catalog)) {
                if (isset($this->role_permission['admin']) && in_array($catalog, $this->role_permission['admin']))
                    return true;
            }
        }
        //权限为空,只根据rank判断即可
        if (is_null($catalog) && is_null($action) && is_null($segment)) {
            return true;
        } else {
            //不存在的权限列表,不允许访问
            return false;
        }
    }

    /**
     * 获取全部角色信息
     * @return array
     */
    function get_role_data() {
        $role_data = $this->cache->get('role_data', true);
        if (!$role_data) {
            $role_data = $this->set_role_data();
        }
        return $role_data;
    }

    /**
     * 写入所有角色数据缓存
     * @return array
     */
    function set_role_data() {
        $role_data = $this->db->simple("SELECT * FROM {pre}role");
        $this->cache->set('role_data', $role_data);
        return $role_data;
    }

}
